package com.azzcs.spring.factory.config;

import com.azzcs.spring.bean.BeanDefinition;
import com.azzcs.spring.bean.PropertyValue;
import com.azzcs.spring.factory.BeanFactory;
import com.azzcs.spring.factory.DefaultListableBeanFactory;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;

/**
 * @Author: wzg
 * @Date: 2020/12/20 上午7:46
 */
public class AutowiredAnnotationBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {

    private DefaultListableBeanFactory beanFactory;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        try {
            Map<String, BeanDefinition> beanDefinitionMap = beanFactory.getBeanDefinitionMap();
            BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
            Set<PropertyValue> propertyValues = beanDefinition.getPropertyValues();
            Class<?> clazz = bean.getClass();
            for (PropertyValue propertyValue : propertyValues) {
                Field field = clazz.getDeclaredField(propertyValue.getName());
                field.setAccessible(true);
                Object value = getBeanValue(propertyValue);
                field.set(bean, value);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(beanName + " bean 自动注入失败");
        }
        return bean;
    }

    private Object getBeanValue(PropertyValue propertyValue) {
        Object bean = null;
        try {
            bean = beanFactory.getBean(propertyValue.getName());
        } catch (Exception e) {

        }
        if (bean == null) {
            bean = beanFactory.getBean(propertyValue.getClazz());
        }
        return bean;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = (DefaultListableBeanFactory) beanFactory;
    }

    @Override
    public int compareTo(Object o) {
        return 0;
    }
}
